#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<assert.h>
#include<termios.h>
#include<string.h>
#include<sys/time.h>
#include<time.h>
#include<sys/types.h>
#include<errno.h>

static int ret;
static int fd;

#define BAUD 9600

int uart_open(int fd,const char *pathname)
{
    fd = open(pathname, O_RDWR|O_NOCTTY); 
    if (-1 == fd)
    { 
        perror("Can't Open Serial Port"); 
		return(-1); 
	   } 
    else
		printf("open %s success!\n",pathname);
    /*测试是否为终端设备*/ 
    if(isatty(STDIN_FILENO)==0) 
		printf("standard input is not a terminal device\n"); 
    else 
		printf("isatty success!\n"); 
    return fd; 
}

int uart_set(int fd,int nSpeed, int nBits, char nEvent, int nStop)//串口名、波特率、数据位、奇偶校验位、停止位
{
     struct termios newtio,oldtio; 
     /*保存测试现有串口参数设置，在这里如果串口号等出错，会有相关的出错信息*/ 
     if  ( tcgetattr( fd,&oldtio)  !=  0) {  
      perror("SetupSerial 1");
	   printf("tcgetattr( fd,&oldtio) -> %d\n",tcgetattr( fd,&oldtio)); 
      return -1; 
     } 
     bzero( &newtio, sizeof( newtio ) ); 
     /*步骤一，设置字符大小*/ 
     newtio.c_cflag  |=  CLOCAL | CREAD;  
     newtio.c_cflag &= ~CSIZE;  
/*设置数据位*/ 
     switch( nBits ) 
     { 

      case 7: 

      newtio.c_cflag |= CS7; 

      break; 

      case 8: 

      newtio.c_cflag |= CS8; 

      break; 

     } 

/*设置奇偶校验位*/ 

     switch( nEvent ) 

     { 

     case 'o':

     case 'O': //奇数 

      newtio.c_cflag |= PARENB; 

      newtio.c_cflag |= PARODD; 

      newtio.c_iflag |= (INPCK | ISTRIP); 

      break; 

     case 'e':

     case 'E': //偶数 

      newtio.c_iflag |= (INPCK | ISTRIP); 

      newtio.c_cflag |= PARENB; 

      newtio.c_cflag &= ~PARODD; 

      break;

     case 'n':

     case 'N':  //无奇偶校验位 

      newtio.c_cflag &= ~PARENB; 

      break;

     default:

      break;

     } 

/*设置波特率*/ 

  switch( nSpeed ) 

     { 

     case 2400: 

      cfsetispeed(&newtio, B2400); 

      cfsetospeed(&newtio, B2400); 

      break; 

     case 4800: 

      cfsetispeed(&newtio, B4800); 

      cfsetospeed(&newtio, B4800); 

      break; 

     case 9600: 

      cfsetispeed(&newtio, B9600); 

      cfsetospeed(&newtio, B9600); 

      break; 

     case 115200: 

      cfsetispeed(&newtio, B115200); 

      cfsetospeed(&newtio, B115200); 

      break; 

     case 460800: 

      cfsetispeed(&newtio, B460800); 

      cfsetospeed(&newtio, B460800); 

      break; 

     default: 

      cfsetispeed(&newtio, B9600); 

      cfsetospeed(&newtio, B9600); 

     break; 

     } 

/*设置停止位*/ 

     if( nStop == 1 ) 

      newtio.c_cflag &=  ~CSTOPB; 

     else if ( nStop == 2 ) 

      newtio.c_cflag |=  CSTOPB; 

/*设置等待时间和最小接收字符*/ 

     newtio.c_cc[VTIME]  = 0; 

     newtio.c_cc[VMIN] = 0; 

/*处理未接收字符*/ 

     tcflush(fd,TCIFLUSH); 

/*激活新配置*/ 
if((tcsetattr(fd,TCSANOW,&newtio))!=0) 

     { 

      perror("com set error"); 

      return -1; 

     } 

  printf("set done!\n"); 

  return 0; 

}

int uart_close(int fd)
{
    assert(fd);
    close(fd);

    /*可以在这里做些清理工作*/

    return 0;
}

int recv_data(int fd, char* recv_buffer,int length)//读取字节数
{
	length=read(fd,recv_buffer,length);
  
	return length;
}

int main()
{
    char r_buf[1024];
    bzero(r_buf,1024);

    fd = uart_open(fd,"/dev/ttyTHS2"); 

  if(fd == -1)  //如果没有成功打开串口
  {
    fprintf(stderr,"uart_open error\n");
    exit(EXIT_FAILURE);
  }

  if(uart_set(fd,BAUD,8,'N',1) == -1)//初始化串口（串口名、波特率、数据位、奇偶校验位、停止位）
  {
    fprintf(stderr,"uart set failed!\n");
    exit(EXIT_FAILURE);
  }

	FILE *fp; //定义数据流fp
	fp = fopen("Record.txt","w+"); //创建文件Record为可读写文件
while(1)
{
    bzero(r_buf,1024); //将r_buf清零
      ret = recv_data(fd,r_buf,44);//从fd文件（指向串口）读出44字节数据, ret为读到的字符长度（没有字符输入时为0）
      if(ret == -1)
      {
        fprintf(stderr,"uart read failed!\n");
        exit(EXIT_FAILURE);
      }
      for(int i=0;i<ret;i++) 
      {
          printf("%02X ", r_buf[i]);
          fprintf(fp,"%02X ", r_buf[i]);
          if(i == ret-1)
          {
              printf("\n");
              fprintf(fp,"\n");
              fflush(fp);
          }
      }
}
}